Skip to content

fix(#153): Ghost objects removed from the in-memory python list of the parent#160

Merged
winwinashwin merged 2 commits intocorridor:mainfrom
Anubhav-2003:fix-issue-153
Apr 13, 2026
Merged

fix(#153): Ghost objects removed from the in-memory python list of the parent#160
winwinashwin merged 2 commits intocorridor:mainfrom
Anubhav-2003:fix-issue-153

Conversation

@Anubhav-2003
Copy link
Copy Markdown

When we were reverting a relationship where a child object was marked for deletion, it was not being removed from the Python's in-memory data-structure (collection). This left 'ghost' objects in the collection. If an autoFlush occurred, SQLAlchemy attempted to lazy-load deferred columns for these ghost objects, causing a KeyError: Deferred loader failed crash, which was especially prevalent if we had a polymorphic sub-class. This fix ensures the items are actively removed from the collection list in memory using collection.remove(value), keeping the Python state perfectly synced with the database session state.


assert len(reverted_car.parts) == 0

with pytest.raises(IndexError):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert len(reverted_car.parts) == 0 should be enough?

you can try doing self.session.flush() and check that it should not raise KeyError (to reproduce original error mentioned in commit msg).

Copy link
Copy Markdown
Author

@Anubhav-2003 Anubhav-2003 Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert len(reverted_car.parts) == 0 should be enough?

you can try doing self.session.flush() and check that it should not raise KeyError (to reproduce original error mentioned in commit msg).

Thank You Ashish for nudging me in the right direction. So essentially the key error was still happening when I tried to flush, so just removing the deleted objects from the in-memory python list wasn't enough. So what I did now is essentially ensure that if something is not in memory and it is already marked for deletion then it is never lazy loaded, and the record just marks it with None. This actually matches the pattern of how we handle non-polymorphic objects, when we can't safely read a value from a deleted object.

Please let me know if I need to make any more changes,
Regards,
Anubhav

@ashish16052
Copy link
Copy Markdown
Collaborator

Great Debugging Skills! Some suggestion for commit structuring:

  1. Might want to squash/fixup "Minor Syntax Fix: Removed unused import of Pytest" to the original commit
  2. "Refactored the assign_attributes method..." should be marked as fix()

@Anubhav-2003
Copy link
Copy Markdown
Author

Great Debugging Skills! Some suggestion for commit structuring:

  1. Might want to squash/fixup "Minor Syntax Fix: Removed unused import of Pytest" to the original commit
  2. "Refactored the assign_attributes method..." should be marked as fix()

Thank You Ashish for the kind words,

I have squashed the minor syntax commit to the original one, and also marked the second commit with the same fix() structure as I did with the first one.

It really helps, when being guided, so thank you again. Please let me know if I need to make any more changes.

Regards,
Anubhav

Copy link
Copy Markdown
Collaborator

@ashish16052 ashish16052 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let me check why CI isn't running - and then we can merge this.

@Anubhav-2003
Copy link
Copy Markdown
Author

LGTM, let me check why CI isn't running - and then we can merge this.

Thank You, Ashish.

@winwinashwin
Copy link
Copy Markdown
Contributor

@Anubhav-2003 I've stabilized CI in main branch. Could you please rebase your changes on top of that?

Let's get this merged once the CI is green 🚀

…t of the parent

When we were reverting a relationship where a child object was marked for deletion, it was not being removed from the Python's in-memory data-structure (collection). This left 'ghost' objects in the collection. If an autoflush occurred, SQLAlchemy attempted to lazy-load deferred columns for these ghost objects, causing a KeyError: Deferred loader failed crash, which was especially prevalent if we had a polymorphic sub-class. This fix ensures the items are actively removed from the collection list in memory using collection.remove(value), keeping the Python state perfectly synced with the database session state.
@Anubhav-2003
Copy link
Copy Markdown
Author

@Anubhav-2003 I've stabilized CI in main branch. Could you please rebase your changes on top of that?

Let's get this merged once the CI is green 🚀

Hi Ashwin, I have rebased my changes on top of the new main branch changes. Please let me know if I need to change anything else. Thank You.

Regards,
Anubhav

… the plugin from improperly triggering lazy-loads on deleted rows.
@Anubhav-2003
Copy link
Copy Markdown
Author

@Anubhav-2003 I've stabilized CI in main branch. Could you please rebase your changes on top of that?
Let's get this merged once the CI is green 🚀

Hi Ashwin, I have rebased my changes on top of the new main branch changes. Please let me know if I need to change anything else. Thank You.

Regards, Anubhav

Sorry for the linting error. I fixed it and merged it with the existing two commits.

@winwinashwin winwinashwin merged commit 1647b92 into corridor:main Apr 13, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants